#pragma once
#include "../safe_handle.hpp"
#include "../inc_windows_h.hpp"
#include "../wxx_error.hpp"

#include <boost/noncopyable.hpp>

namespace wxx
{
	using namespace safe_handles;

	namespace detail
	{
		struct heap_handle : zero_or_minus_one_is_invalid
		{
			typedef HANDLE handle_type;

			void dispose(handle_type h) throw(...)
			{
				ensure_success_win32(::HeapDestroy(h));
			}

			bool dispose(handle_type h, std::nothrow_t) throw()
			{
				return ::HeapDestroy(h) == TRUE;
			}
		};
	}

	struct heap : safe_handle<detail::heap_handle>, boost::noncopyable
	{
		enum heap_type
		{
			normal = 0,
			executable = HEAP_CREATE_ENABLE_EXECUTE, 
			nonserialized = HEAP_NO_SERIALIZE,
		};

		explicit heap(enum heap_type type = normal, 
			           size_t initialSize = 0, 
			           size_t maximumSize = 0)
			: safe_handle(create_heap(type, initialSize, maximumSize))
		{
		}

		explicit heap(handle_type hHeap) throw()
			: safe_handle(hHeap)
		{
		}

		bool terminate_on_corruption() const throw(...)
		{
			return TRUE == ::HeapQueryInformation(handle(), HeapEnableTerminationOnCorruption, NULL, 0, NULL);
		}
	private:
		static handle_type create_heap(heap_type type, size_t initial, size_t maximum);
	};
};